package com.crm.jdy.controller.activiti;
import com.crm.jdy.common.dto.activiti.ProcessDto;
import com.crm.jdy.common.utils.api.ResultVo;
import com.crm.jdy.common.utils.currentlimiting.RateLimit;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
/**
*
* <p>说明： 流程定义表API接口层</P>
* @version: V1.0
* @author: kong
* @time    2020年8月20日
*
*/
@Validated
@Api(tags = "flowBillDefinition", description = "公司流程定义表")
@RestController
@RequestMapping("/flowBillDefinition")
@Slf4j
public class FlowBillDefinitionController {

    @Autowired
    TaskService taskService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    RepositoryService repositoryService;

    @Autowired
    HistoryService historyService;

    @RateLimit()
    @ApiOperation(value = "上传部署设计好的流程图", notes = "参数:上传部署设计好的流程图")
    @PostMapping("/seleteUserPermission")
    public ResultVo seleteDepartment(@ApiParam(value = "流程图压缩包", required = true) MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
//        //把文件的后缀去掉
        fileName = fileName.substring(0, fileName.lastIndexOf("."));
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println(defaultProcessEngine);
        ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream());
        Deployment deployment = defaultProcessEngine.getRepositoryService()
                .createDeployment()
                .name(fileName)
                .addZipInputStream(zipInputStream)
                .deploy();
        if (null != deployment){
            return ResultVo.success("部署成功");
        }
        return ResultVo.failed("部署失败");
    }

    @RateLimit()
    @ApiOperation(value = "流程的部署列表", notes = "参数:流程的部署列表")
    @GetMapping(value = "/getFlowChart")
    public ResultVo getFlowChart() {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionVersion().asc().list();
        List<ProcessDto> list1 = new ArrayList<>();
        for (ProcessDefinition processDefinition : list) {
            ProcessDto processDto = new ProcessDto();
            processDto.setCategory(processDefinition.getCategory());
            processDto.setDeploymentId(processDefinition.getDeploymentId());
            processDto.setDescription(processDefinition.getDescription());
            processDto.setDiagramResourceName(processDefinition.getDiagramResourceName());
            processDto.setId(processDefinition.getTenantId());
            processDto.setKey(processDefinition.getKey());
            processDto.setResourceName(processDefinition.getResourceName());
            processDto.setTenantId(processDefinition.getTenantId());
            processDto.setName(processDefinition.getName());
            processDto.setId(processDefinition.getId());
            processDto.setVersion(String.valueOf(processDefinition.getVersion()));
            list1.add(processDto);
        }
        return ResultVo.success(list1);
    }

    @RateLimit()
    @ApiOperation(value = "流程的定义", notes = "参数:流程的定义")
    @PostMapping("/seleteFlowDataDefinition")
    public ResultVo seleteFlowDataDefinition(@ApiParam(name = "processDto", required = false)
                                             @RequestBody ProcessDto processDto) {
        ProcessDto processDto1 = new ProcessDto();
        ProcessInstance processInstance = null;
        // 3.创建流程实例
        if (processDto.getMap() == null) {
            if (processDto.getId() == null) {
                processInstance = runtimeService.startProcessInstanceByKey(processDto.getKey());
            } else {
                processInstance = runtimeService.startProcessInstanceById(processDto.getId());
            }
        }else{
            processInstance = runtimeService.startProcessInstanceByKey(processDto.getKey(), processDto.getName(), processDto.getMap());
        }
        // 4.输出实例的相关信息
        System.out.println("流程部署id:" + processInstance.getDeploymentId());//null
        System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());//holiday:1:4
        System.out.println("流程实例id:" + processInstance.getId());//2501
        System.out.println("流程活动id:" + processInstance.getActivityId());//null

        processDto1.setDeploymentId(processInstance.getDeploymentId());
        processDto1.setDescription(processInstance.getDescription());
        processDto1.setId(processInstance.getTenantId());
        processDto1.setTenantId(processInstance.getTenantId());
        processDto1.setName(processInstance.getName());
        processDto1.setId(processInstance.getId());
        processDto1.setProcessDefinitionId(processInstance.getProcessDefinitionId());
        processDto1.setActivityId(String.valueOf(processInstance.getActivityId()));
        return ResultVo.success(processDto1);
    }

    @RateLimit()
    @ApiOperation(value = "根据人员名称查询流程", notes = "参数:根据人员名称查询流程")
    @GetMapping("/seleteAlanDrentqwe")
    public ResultVo selelianDrenqwet(@NotNull String processDefinitionId){
        //根据接受人获取该用户的任务
        List<Task> tasks = taskService.createTaskQuery()
                .taskAssignee(processDefinitionId)
                .list();
        for (Task task : tasks) {
            System.out.println("ID:" + task.getId() + ",姓名:" + task.getName() + ",接收人:" + task.getAssignee() + ",开始时间:" + task.getCreateTime());
        }
        return ResultVo.success(tasks);
    }

    @ApiOperation(value = "人员定义流程的查询", notes = "参数:人员定义流程的查询")
    @GetMapping("/seleteAnDrentqwe")
    public ResultVo seleanDrenqwet(String processDefinitionId) {
        //根据接受人获取该用户的任务
//        List<Task> taskList  = taskService.createTaskQuery().taskAssignee("user1").list();
        String assignee =  processDefinitionId;
        List<Task> list = taskService//与正在执行的任务管理相关的Service
                .createTaskQuery()//创建任务查询对象
                /**查询条件（where部分）*/
                .taskAssignee(assignee)//指定个人任务查询，指定办理人
//						.taskCandidateUser(candidateUser)//组任务的办理人查询
//						.processDefinitionId(processDefinitionId)//使用流程定义ID查询
//						.processInstanceId(processInstanceId)//使用流程实例ID查询
//						.executionId(executionId)//使用执行对象ID查询
                /**排序*/
                .orderByTaskCreateTime().asc()//使用创建时间的升序排列
                /**返回结果集*/
//						.singleResult()//返回惟一结果集
//						.count()//返回结果集的数量
//						.listPage(firstResult, maxResults);//分页查询
                .list();//返回列表
        List<ProcessDto> list1 = new ArrayList<>();
        if(list!=null && list.size()>0){
            for(Task task:list){
                ProcessDto   processDto =  new ProcessDto();
                processDto.setId(task.getId());
                processDto.setName(task.getName());
                processDto.setCreateTime(task.getCreateTime().toString());
                processDto.setAssignee(task.getAssignee());
                processDto.setProcessInstanceId(task.getProcessInstanceId());
                processDto.setExecutionId(task.getExecutionId());
                processDto.setProcessDefinitionId(task.getProcessDefinitionId());
                System.out.println("任务ID:"+task.getId());
                System.out.println("任务名称:"+task.getName());
                System.out.println("任务的创建时间:"+task.getCreateTime());
                System.out.println("任务的办理人:"+task.getAssignee());
                System.out.println("流程实例ID："+task.getProcessInstanceId());
                System.out.println("执行对象ID:"+task.getExecutionId());
                System.out.println("流程定义ID:"+task.getProcessDefinitionId());
                System.out.println("########################################################");
                list1.add(processDto);
            }
        }
        return ResultVo.success(list1);
    }


    @RateLimit()
    @ApiOperation(value = "根据任务ID完成任务", notes = "参数:根据任务ID完成任务")
    @GetMapping("/seleteAlanDntqwe")
    public ResultVo seleliarenqwet(String name){
        System.out.println("name"+name);
        String taskId = name;
        //完成请假申请任务
        taskService.complete(taskId);

//        RuntimeService runtimeService = processEngine.getRuntimeService();
//        ProcessInstanceQuery createProcessInstanceQuery = runtimeService.createProcessInstanceQuery();
//        ProcessInstanceQuery processInstanceId = createProcessInstanceQuery.processInstanceId("1111");
//        ProcessInstance singleResult = processInstanceId.singleResult();
//        if(singleResult==null){
//            System.out.println("执行完毕");
//        }else{
//            System.out.println("正在执行");
//        }
        return ResultVo.success();
    }


    @RateLimit()
    @ApiOperation(value = "历史流程查询", notes = "参数:历史流程查询")
    @GetMapping("/seletelishiliucheng")
    public ResultVo startProcessInstance(@NotNull String name) {
        List<HistoricActivityInstance> list = historyService  // 历史相关Service
                .createHistoricActivityInstanceQuery() // 创建历史活动实例查询
                .processInstanceId(name) // 执行流程实例id
                .list();
        for (HistoricActivityInstance hai : list){
            System.out.println("活动ID:" + hai.getId());
            System.out.println("活动ID:" + hai.getActivityId());
            System.out.println("活动ID:" + hai.getActivityName());
            System.out.println("活动ID:" + hai.getProcessInstanceId());
            System.out.println("活动ID:" + hai.getProcessDefinitionId());
            System.out.println("活动ID:" + hai.getId());
            System.out.println("------------------");
        }
        return ResultVo.success();
    }


    @RateLimit()
    @ApiOperation(value = "根据审批人完成任务", notes = "参数:根据审批人完成任务")
    @GetMapping("/comentWancheng")
    public ResultVo comentWancheng(String name){
        Map<String, Object> variables=new HashMap<>();
        variables.put("decision","驳回");
//        variables.put("user2","user2");
        taskService.complete(name ,variables);
//        RuntimeService runtimeService = processEngine.getRuntimeService();
//        ProcessInstanceQuery createProcessInstanceQuery = runtimeService.createProcessInstanceQuery();
//        ProcessInstanceQuery processInstanceId = createProcessInstanceQuery.processInstanceId("1111");
//        ProcessInstance singleResult = processInstanceId.singleResult();
//        if(singleResult==null){
//            System.out.println("执行完毕");
//        }else{
//            System.out.println("正在执行");
//        }
        return ResultVo.success();
    }

//    @ApiOperation(value = "定义流程的查询", notes = "参数:定义流程的查询")
//    @GetMapping("/seleteAlanDrtmentqwe")
//    public ResultVo selelianDrtmenqwet(String processDefinitionId) {
//        //1.得到ProcessEngine对象
//        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        //2.创建RepositoryService对象
//        RepositoryService repositoryService = processEngine.getRepositoryService();
//        //3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器
//        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//        //4.设置条件，并查询出当前的所有流程定义   查询条件：流程定义的key=holiday
//        //orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序
//        List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey(processDefinitionId)
//                .orderByProcessDefinitionVersion()
//                .desc().list();
//        System.out.println("==============="+list.size());
//        //5.输出流程定义信息
//        for(ProcessDefinition processDefinition :list){
//            System.out.println("流程定义ID："+processDefinition.getId());
//            System.out.println("流程定义名称："+processDefinition.getName());
//            System.out.println("流程定义的Key："+processDefinition.getKey());
//            System.out.println("流程定义的版本号："+processDefinition.getVersion());
//            System.out.println("流程部署的ID:"+processDefinition.getDeploymentId());
//        }
//        return ResultVo.success(list);
//    }


//
////    @ApiOperation(value = "查询定义的流程", notes = "参数:查询已经定义的流程")
////    @GetMapping("/seleteFlowDefinition")
////    public ResultVo seleteFlowDefinition() {
////        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
////        DeploymentQuery query = processEngine.getRepositoryService().createDeploymentQuery();
////        List<Deployment> list = query.list();
////        // 增强for循环简写iter
////        for (Deployment deployment : list) {
////            String id = deployment.getId();
////            String idt1 =  deployment.getName();
////            Date deploymentTime = deployment.getDeploymentTime();
////            String idt3 =  deployment.getKey();
////            String id4t = deployment.getTenantId();
////            log.info("流程定义的ID",id);
////            log.info("流程定义的Name",idt1);
////            log.info("流程定义的Time",deploymentTime);
////            log.info("流程定义的Key",idt3);
////            log.info("流程定义的TenantId",id4t);
////            System.out.println("====================");
////        }
////        return ResultVo.success();
////    }
//
//
//    @ApiOperation("新增食品安全问题分类")
//    @PostMapping("addjdyAppletFoodSafetyProblemsReult")
//    public ResultVo addkeyPointPracticableService( @ApiParam(name = "users", required = true)
//                                                   @RequestBody  FlowBillDefinition users){
//        boolean save = jdyAppletFoodSafetyProblemsReultService.save(users);
//        if(save){
//            redisUtil.del("seletejdyAppletFoodSafetyProblemsReult");
//            return ResultVo.success();
//        }
//        return ResultVo.failed();
//    }
//
//
//
////    @ApiOperation(value = "食品安全问题分类", notes = "参数:食品安全问题分类")
////    @PostMapping("/seletejdyAppletFoodSafetyProblemsReult")
////    public ResultVo seleteDepartment( @ApiParam(name = "jdyAppletFoodSafetyDto", required = false)
////                                      @RequestBody JdyAppletFoodClassify jdyAppletFoodSafetyDto){
////        if(jdyAppletFoodSafetyDto != null){
////            List<JdyAppletFoodClassify> list = jdyAppletFoodSafetyProblemsReultService.seleteList(jdyAppletFoodSafetyDto);
////            return  ResultVo.success(list);
////        }else{
////            if( redisUtil.get("jdyAppletFoodClassify") == null){
////                List<JdyAppletFoodClassify> list = jdyAppletFoodSafetyProblemsReultService.seleteList(jdyAppletFoodSafetyDto);
////                redisUtil.set("jdyAppletFoodClassify",list);
////                return  ResultVo.success(list);
////            }else{
////                return  ResultVo.success(redisUtil.get("jdyAppletFoodClassify"));
////            }
////        }
////    }
//
////    @ApiOperation("更新食品安全问题分类")
////    @PostMapping("updatejdyAppletFoodSafetyProblemsReult")
////    public ResultVo updatekeyPointPracticableService(@ApiParam(name = "userPermission", required = true)
////                                                     @RequestBody JdyAppletFoodClassify userPermission){
////        boolean b = jdyAppletFoodSafetyProblemsReultService.updateById(userPermission);
////        if(b){
////            redisUtil.del("jdyAppletFoodClassify");
////            return ResultVo.success();
////        }
////        return ResultVo.failed();
////    }
////
//
////
////    @ApiOperation("删除食品安全问题分类")
////    @DeleteMapping("deletejdyAppletFoodSafetyProblemsReult/{id}")
////    public ResultVo deletekeyPointPracticableService(@ApiParam(name = "id", value = "权限ID", required = true) @PathVariable String  id){
////        boolean b = jdyAppletFoodSafetyProblemsReultService.removeById(id);
////        if(b){
////            redisUtil.del("seletejdyAppletFoodSafetyProblemsReult");
////            return ResultVo.success();
////        }
////        return ResultVo.failed();
////    }
//
//    @ApiOperation(value = "ceshi", notes = "参数:流程的定义")
//    @PostMapping("/ceshi")
//    public ResultVo ceshi(@ApiParam(name = "jdyAppletFoodSafetyDto", required = false)
//                                             @RequestBody FlowActivitStartVo jdyAppletFoodSafetyDto) {
//
////        List<ProcessDefinition> list = jdyAppletFoodSafetyProblemsReultService.createProcessDefinitionQuery();
//
////        return ResultVo.success(list);
//
////        //1.得到ProcessEngine对象
////        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//////        //2.创建RepositoryService对象
////        RepositoryService repositoryService = processEngine.getRepositoryService();
//        //3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器
////        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//        //4.设置条件，并查询出当前的所有流程定义   查询条件：流程定义的key=holiday
//        //orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序
//
//        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionVersion().asc().list();
//        System.out.println("==============="+list.size());
//        //5.输出流程定义信息
//        for(ProcessDefinition processDefinition :list){
//            System.out.println("流程定义ID："+processDefinition.getId());
//            System.out.println("流程定义名称："+processDefinition.getName());
//            System.out.println("流程定义的Key："+processDefinition.getKey());
//            System.out.println("流程定义的版本号："+processDefinition.getVersion());
//            System.out.println("流程部署的ID:"+processDefinition.getDeploymentId());
//        }
//        return ResultVo.success(list);
//
////        return  null;
//    }


//    暂时用不着
//    @ApiOperation(value = "查询当前用户的任务列表", notes = "参数:查询当前用户的任务列表")
////    @PostMapping("/seleteAllChejnDrtment/")
////    public ResultVo seleteAllCheanDrtment(@ApiParam(name = "jdyAppletFoodSafetyDto", required = false)
////                                          @RequestBody JdyAppletFoodSafetyDto jdyAppletFoodSafetyDto) {
////
////        //3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
////        List<Task> list = taskService.createTaskQuery()
////                .processDefinitionKey(jdyAppletFoodSafetyDto.getId())
////                .taskAssignee(jdyAppletFoodSafetyDto.getName())
////                .list();
////        //4.任务列表的展示
////        for (int i =0;i< list.size();i++){
////            System.out.println("流程实例ID:" + list.get(i).getProcessInstanceId());//2501
////            System.out.println("任务ID:" + list.get(i).getId());  //2505
////            System.out.println("任务负责人:" + list.get(i).getAssignee());//zhangsan
////            System.out.println("任务名称:" + list.get(i).getName());//填写请假申请单
////        }
////        return null;
////    }
//
//
//}

}